﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Web;
using System.Web.Caching;

using CreateYourWorld.DataModels;
using CreateYourWorld.DataAccess;

namespace CreateYourWorld.Infrastructure
{
    public class WorldService :IWorldService
    {
        private IWorldRepository worldRepository = null;

        private Cache cache = HttpContext.Current.Cache;

        public WorldService(IWorldRepository WorldRepository)
        {
            worldRepository = WorldRepository;
        }

        public SessionModel getSession(string username, string password)
        {
            return worldRepository.getSession(username, password);
        }

        public PlayerBaseModel getPlayerData(Int64 sessionID)
        {
            return worldRepository.getPlayerData(sessionID);
        }
        public FieldBaseModel getFieldData(Int32 fieldType)
        {
            try
            {
                string cacheName = "Field" + fieldType;
                var field = cache[cacheName];
                if (field == null)
                {
                    field = worldRepository.getFieldData(fieldType);
                    cache.Add(cacheName, (FieldBaseModel)field, null, DateTime.Now.AddHours(1), TimeSpan.Zero, CacheItemPriority.High, null);
                }
                return field as FieldBaseModel;
            }
            catch { }
            return null;
        }
        public CreatureBaseModel getCreatureData(Int32 creatureType)
        {
            try
            {
                string cacheName = "Creature" + creatureType;
                var creature = cache[cacheName];
                if (creature == null)
                {
                    creature = worldRepository.getCreatureData(creatureType);
                    cache.Add(cacheName, (CreatureBaseModel)creature, null, DateTime.Now.AddHours(1), TimeSpan.Zero, CacheItemPriority.High, null);
                }
                return creature as CreatureBaseModel;
            }
            catch { }
            return null;
        }
        public ItemBaseModel getItemData(Int32 itemType)
        {
            try
            {
                string cacheName = "Item" + itemType;
                var item = cache[cacheName];
                if (item == null)
                {
                    item = worldRepository.getItemData(itemType);
                    cache.Add(cacheName, (ItemBaseModel)item, null, DateTime.Now.AddHours(1), TimeSpan.Zero, CacheItemPriority.High, null);
                }
                return item as ItemBaseModel;
            }
            catch { }
            return null;
        }

        public PlayerModel getPlayer(Int64 sessionID)
        {
            PlayerModel player = worldRepository.getPlayer(sessionID);
            if (player == null) return null;

            var fieldOfView = worldRepository.getWorldFields();
            if (fieldOfView == null) return null;

            FieldModel playerField = fieldOfView.Where(p => p.ID == player.FieldID).First();
            player.WorldID = playerField.WorldID;
            player.xPosition = playerField.X;
            player.yPosition = playerField.Y;

            player.PlayerField = new PlayerFieldModel();

            #region get items on player-field
            var items = worldRepository.getFieldItems(player.FieldID);
            if (items != null)
            {
                player.PlayerField.Items = items.ToList();
                foreach (ItemModel item in player.PlayerField.Items)
                {
                    item.Data = getItemData(item.ItemType);
                }
            }
            #endregion

            #region get creatures on player-field
            var creatures = worldRepository.getFieldCreatures(player.FieldID);
            if (creatures != null)
            {
                player.PlayerField.Creatures = creatures.ToList();
                foreach (CreatureModel creature in player.PlayerField.Creatures)
                {
                    creature.Data = getCreatureData(creature.CreatureType);
                }
            }
            #endregion

            fieldOfView = fieldOfView.Where(p =>
                p.WorldID == player.WorldID &&
                p.X >= player.xPosition - 3 &&
                p.X <= player.xPosition + 3 &&
                p.Y >= player.yPosition - 3 &&
                p.Y <= player.yPosition + 3);
            if (fieldOfView == null) return null;

            foreach (FieldModel field in fieldOfView)
            {
                field.Data = getFieldData(field.FieldType);
                field.NumberOfCreatures = worldRepository.getFieldCreatures(field.ID).Count();

                player.setField(field.X - player.xPosition, field.Y - player.yPosition, field);
            }

            return player;
        }

        public bool updatePlayerPosition(Int64 sessionID, int movedX, int movedY)
        {
            return worldRepository.updatePlayerPosition(sessionID, movedX, movedY);
        }
    }
}
